﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using System.Configuration;

namespace PATBController
{
    class Program
    {
        private static bool bForceCleanExit = false;
        private static bool bInitializationPass = true;
        static void Main(string[] args)
        {
            Execute();
        }
        public static void Execute()
        {
            Logger.Log(0, "Execute", "Initializing");
            ATBManagerClass ATBManager = new ATBManagerClass();

            // comment next line if you don't want a file log
            Logger.Init(ConfigurationManager.AppSettings["WorkingRootFolder"]);

            // time to sleep between iterations
            int iIterationSleep = int.Parse(ConfigurationManager.AppSettings["IterationSleep"]);
            Logger.Log(0, "Execute", "Iteration wait time of (seconds) " + (iIterationSleep / 1000).ToString());

            while (true)
            {
                Logger.Post("Execute", "-------------------------NEW PASS-------------------------");
                Logger.Post("Execute", "-- Press [E] to exit cleanly (wait for tests to finish)");
                Logger.Post("Execute", "-- Press [X] to exit immediately");
                try
                {
                    ATBManager.ReportStatus();

                    Logger.Post("Execute", "-Checking status of active tests");
                    ATBManager.CheckRunningTests();

                    if(bInitializationPass)
                    {
                        Logger.Post("Execute", "-Initializaing any non-allocated virtual machines");
                        ATBManager.InitVirtualMachines();
                    }
                    if (!bForceCleanExit)
                    {
                        Logger.Post("Execute", "-Checking to determine if any runs need to be started...");
                        ATBManager.CheckStartRuns();
                        Logger.Post("Execute", "-Checking to determine if any tests need to be started...");
                        ATBManager.CheckStartTest();
                    }
                    Logger.Post("Execute", "-Checking to determine if any tests need results posted...");
                    ATBManager.CheckPostResults();

                    Logger.Post("Execute", "-Refreshing run list and test machines list");
                    ATBManager.Refresh();

                    if(bForceCleanExit)
                    {
                        Logger.Post("Execute", "-Checking if we can exit");
                        if(ATBManager.CheckCleanExitStatus())
                        {
                            Logger.Log(0, "Execute", "Clean exit - concluded");
                            return;
                        }
                    }

                    bInitializationPass = false;
                }
                catch( Exception ex )
                {
                    Logger.PostException(ex);
                }

                ATBManager.ReportStatus();
                Logger.Post("Execute", "------------------------PASS DONE-------------------------");
                Logger.Post("Execute", "-- Press [E] to exit cleanly (wait for tests to finish)");
                Logger.Post("Execute", "-- Press [X] to exit immediately");

                // wait and watch the keyboard at the same time
                string sKeypresed = KeyReader.Read(iIterationSleep);
                if(!string.IsNullOrEmpty(sKeypresed))
                {
                    // X means exit immediately
                    if( sKeypresed.Equals("x") )
                    {
                        Logger.Log(0, "Execute", "[X] key pressed, exiting immediately");
                        return;
                    }
                    // A means exit cleanly, wait for tests to complete
                    if( sKeypresed.Equals("e") )
                    {
                        // TODO - Implement Clean Exit Feature
                        Logger.Log(0, "Execute", "[E] key pressed, exiting once current tests are complete (no new ones will be started)");
                        bForceCleanExit = true;
                        if (ATBManager.CheckCleanExitStatus())
                        {
                            Logger.Log(0, "Execute", "Clean exit - concluded");
                            return;
                        }
                    }
                }
            }
        }
    }
    class KeyReader
    {
        private static Thread inputThread;
        private static AutoResetEvent getInput, gotInput;
        private static string input;

        static KeyReader()
        {
            inputThread = new Thread(reader);
            inputThread.IsBackground = true;
            inputThread.Start();
            getInput = new AutoResetEvent(false);
            gotInput = new AutoResetEvent(false);
        }

        private static void reader()
        {
            while (true)
            {
                getInput.WaitOne();
                input = Console.ReadKey(true).KeyChar.ToString().ToLower();
                gotInput.Set();
            }
        }

        public static string Read(int timeOutMillisecs)
        {
            getInput.Set();
            bool success = gotInput.WaitOne(timeOutMillisecs);
            if (success)
                return input;
            else
                return string.Empty;
        }
    }
}
